Popular Searches
Popular Course Categories
Popular Courses

PyTest Basics

TestNG / PyTest

PyTest Basics

PyTest is a popular Python testing framework used to write, organize, execute, and maintain automated tests. It provides a simple syntax for creating test cases and includes powerful features such as fixtures, assertions, parameterization, markers, test discovery, plugins, and detailed test reporting.

PyTest is widely used for unit testing, integration testing, API testing, web automation, and Selenium-based browser automation. Its simple structure allows testers and developers to create readable and maintainable automated test suites with less boilerplate code.

In Selenium automation, PyTest can be combined with Selenium WebDriver to automate browsers, validate web application functionality, execute multiple test scenarios, manage browser setup and cleanup, and generate test execution reports.

Course Resource: Selenium Training | Register for Course Demo


1. What is PyTest?

PyTest is an open-source testing framework for Python. It is designed to make writing and running tests simple while also supporting advanced testing requirements.

PyTest can be used to test individual functions, classes, modules, APIs, databases, web applications, and complete application workflows.

One of the major advantages of PyTest is that a basic test can be written using a normal Python function and a simple assert statement.

def test_addition():

    result = 10 + 20

    assert result == 30

If the assertion is true, the test passes. If the assertion is false, PyTest reports the test as failed.


2. Why is PyTest Important?

PyTest is important because it provides a flexible and scalable way to automate software testing using Python.

  • Simple and readable test syntax.
  • Powerful assertion support.
  • Automatic test discovery.
  • Fixtures for setup and cleanup.
  • Parameterized testing.
  • Test grouping using markers.
  • Detailed failure information.
  • Large plugin ecosystem.
  • Easy integration with Selenium.
  • Easy integration with API testing tools.
  • Supports parallel test execution through plugins.
  • Can generate different types of test reports.
  • Works well with CI/CD systems.


3. PyTest Installation

PyTest can be installed using Python's package manager, pip.

pip install pytest

After installation, verify the PyTest version:

pytest --version

A successful installation displays the installed PyTest version and related information.


4. Checking Python Installation

Before installing PyTest, Python should be installed on the system.

python --version

On some systems, the following command may be required:

python3 --version

The Python version can also be checked from an IDE terminal such as PyCharm or Visual Studio Code.


5. Creating a Basic PyTest Test

A PyTest test can be created using a Python function whose name starts with test_.

def test_login():

    username = "admin"

    password = "admin123"

 

    assert username == "admin"

    assert password == "admin123"

The function can then be executed by PyTest.


6. PyTest Test Naming Convention

PyTest uses naming conventions to automatically discover tests.

Common test file naming patterns include:

test_login.py

test_search.py

test_checkout.py

Test functions commonly follow this pattern:

def test_login():

    pass

 

def test_search():

    pass

 

def test_checkout():

    pass

Following the standard naming convention makes automatic test discovery easier.


7. PyTest Test Discovery

Test discovery is the process by which PyTest automatically identifies test files, test functions, and test classes.

By default, PyTest commonly discovers files beginning with test_ or ending with _test.py.

For example:

project/

|-- test_login.py

|-- test_search.py

|-- test_checkout.py

Running:

pytest

allows PyTest to search the current directory and execute discovered tests.


8. Running PyTest Tests

The basic command for executing PyTest tests is:

pytest

To run a specific test file:

pytest test_login.py

To run a specific test function:

pytest test_login.py::test_login

To display more detailed output:

pytest -v

The -v option means verbose mode.


9. Basic PyTest Execution Flow

PyTest Command

      |

      v

Test Discovery

      |

      v

Collect Test Files

      |

      v

Collect Test Functions

      |

      v

Execute Tests

      |

      v

Assertions

      |

      v

Pass / Fail / Skip

      |

      v

Test Result

      |

      v

Report


10. Assertions in PyTest

Assertions are used to verify whether the actual result matches the expected result.

def test_addition():

    result = 5 + 5

    assert result == 10

If the condition is true, the test passes.

If the condition is false:

def test_addition():

    result = 5 + 5

    assert result == 20

PyTest marks the test as failed and provides information about the assertion failure.


11. Common Assertion Examples

def test_assertions():

    assert 10 == 10

    assert "Python" == "Python"

    assert 10 > 5

    assert 5 < 10

    assert "PyTest" in "PyTest Automation"

    assert True

Assertions can be used to validate values, strings, collections, Boolean conditions, and application results.


12. Assertion Failure Example

def test_failure():

    expected = "Login Successful"

    actual = "Login Failed"

 

    assert actual == expected

The test fails because the actual value does not match the expected value.


13. PyTest Test Class

Multiple related test methods can be organized inside a class.

class TestLogin:

 

    def test_valid_login(self):

        assert True

 

    def test_invalid_login(self):

        assert True

 

    def test_logout(self):

        assert True

PyTest can discover test classes whose names follow its test-class naming conventions, such as classes beginning with Test.


14. Test Class Example

class TestCalculator:

 

    def test_addition(self):

        assert 10 + 20 == 30

 

    def test_subtraction(self):

        assert 20 - 10 == 10

 

    def test_multiplication(self):

        assert 5 * 5 == 25

 

    def test_division(self):

        assert 20 / 5 == 4

Grouping related tests into classes can improve test organization.


15. PyTest Fixtures

Fixtures are one of the most important features of PyTest. They provide reusable setup and preparation logic for tests.

Fixtures can be used for:

  • Browser initialization.
  • Database connections.
  • API clients.
  • Test data preparation.
  • Login setup.
  • File preparation.
  • Environment configuration.
  • Cleanup activities.

import pytest

 

@pytest.fixture

def sample_data():

    return 10

 

def test_value(sample_data):

    assert sample_data == 10


16. Fixture Execution Flow

Test Starts

    |

    v

Fixture Executes

    |

    v

Fixture Provides Data / Resource

    |

    v

Test Method Executes

    |

    v

Assertion

    |

    v

Test Completes

    |

    v

Fixture Cleanup


17. Fixture with Selenium

Fixtures are commonly used to create and close Selenium WebDriver instances.

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    driver.maximize_window()

    yield driver

    driver.quit()

 

def test_google_title(driver):

    driver.get("https://www.google.com")

    assert "Google" in driver.title

Here, the fixture creates the browser before the test and closes the browser after the test.


18. Understanding yield in Fixtures

The yield statement is commonly used in PyTest fixtures to separate setup and teardown logic.

@pytest.fixture

def browser():

    driver = webdriver.Chrome()

 

    yield driver

 

    driver.quit()

The code before yield runs during setup. The code after yield runs during cleanup.


19. Fixture Scope

PyTest fixtures support different scopes that control how frequently the fixture is created.

ScopeMeaning
functionRuns for each test function.
classRuns once for each test class.
moduleRuns once for each module.
packageRuns once for a package.
sessionRuns once for the complete test session.


20. Function Scope Fixture

@pytest.fixture(scope="function")

def browser():

    driver = webdriver.Chrome()

    yield driver

    driver.quit()

A function-scoped fixture is created separately for each test function that requests it.


21. Module Scope Fixture

@pytest.fixture(scope="module")

def browser():

    driver = webdriver.Chrome()

    yield driver

    driver.quit()

A module-scoped fixture can be shared by tests within the same Python module.


22. Session Scope Fixture

@pytest.fixture(scope="session")

def environment():

    print("Initialize test environment")

    yield

    print("Cleanup test environment")

A session-scoped fixture can be useful for resources that should be initialized once for the entire test session.


23. PyTest Parameterization

Parameterization allows the same test to execute with different input values.

import pytest

 

@pytest.mark.parametrize(

    "a,b,expected",

    [

        (10, 20, 30),

        (5, 5, 10),

        (100, 50, 150)

    ]

)

def test_addition(a, b, expected):

    assert a + b == expected

The same test executes once for every data set.


24. Parameterization Flow

Test Function

     |

     v

@pytest.mark.parametrize

     |

     +---- Data Set 1

     |

     +---- Data Set 2

     |

     +---- Data Set 3

     |

     v

Multiple Test Executions


25. Parameterized Selenium Test

Parameterization is very useful in Selenium automation.

import pytest

from selenium import webdriver

 

@pytest.mark.parametrize(

    "url",

    [

        "https://www.google.com",

        "https://www.example.com"

    ]

)

def test_title(url):

    driver = webdriver.Chrome()

    driver.get(url)

 

    assert driver.title != ""

 

    driver.quit()


26. PyTest Markers

Markers are used to categorize and selectively execute tests.

import pytest

 

@pytest.mark.smoke

def test_login():

    assert True

 

@pytest.mark.regression

def test_search():

    assert True

Markers make it easier to organize large test suites.


27. Registering Custom Markers

Custom markers can be registered in the pytest.ini file.

[pytest]

markers =

    smoke: smoke test cases

    regression: regression test cases

    login: login related tests

This provides a clear definition for custom markers used in the project.


28. Running Tests by Marker

To run only smoke tests:

pytest -m smoke

To run regression tests:

pytest -m regression

To run login tests:

pytest -m login


29. Skipping Tests

PyTest allows tests to be skipped when they should not execute under a particular condition.

import pytest

 

@pytest.mark.skip(reason="Feature is not ready")

def test_new_feature():

    assert True

The test appears as skipped instead of failed.


30. Conditional Skipping

A test can be skipped based on a condition.

import pytest

import sys

 

@pytest.mark.skipif(

    sys.platform == "win32",

    reason="Not supported on Windows"

)

def test_linux_feature():

    assert True

This is useful when tests depend on a specific operating system, Python version, browser, or environment.


31. Expected Failures

The xfail marker can be used for tests that are currently expected to fail.

import pytest

 

@pytest.mark.xfail(reason="Known application defect")

def test_known_issue():

    assert 1 == 2

This allows known issues to be documented without treating them as unexpected failures.


32. PyTest Configuration File

PyTest can be configured using files such as pytest.ini.

[pytest]

testpaths = tests

python_files = test_*.py

python_functions = test_*

addopts = -v

Configuration files help standardize test execution across the project.


33. PyTest Project Structure

A basic PyTest automation project can be organized as follows:

project/

|-- tests/

|   |-- test_login.py

|   |-- test_search.py

|   |-- test_checkout.py

|

|-- pages/

|   |-- login_page.py

|   |-- search_page.py

|   |-- checkout_page.py

|

|-- utilities/

|   |-- driver_factory.py

|   |-- config_reader.py

|

|-- conftest.py

|-- pytest.ini

|-- requirements.txt


34. Understanding conftest.py

conftest.py is a special PyTest file commonly used to define shared fixtures and test configuration.

Fixtures defined in an appropriate conftest.py can be automatically discovered and used by test files without importing them manually.

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    yield driver

    driver.quit()

This fixture can then be used by tests in the relevant test directory.


35. Selenium Fixture Using conftest.py

A common Selenium project design is to place browser setup inside conftest.py.

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    driver.maximize_window()

 

    yield driver

 

    driver.quit()

Test file:

def test_google(driver):

    driver.get("https://www.google.com")

    assert "Google" in driver.title


36. PyTest with Selenium WebDriver

PyTest and Selenium WebDriver can be combined to build browser automation frameworks.

from selenium import webdriver

 

def test_google_search():

    driver = webdriver.Chrome()

 

    driver.get("https://www.google.com")

 

    assert "Google" in driver.title

 

    driver.quit()

In production frameworks, browser creation and cleanup are usually moved into fixtures.


37. Selenium Login Test with PyTest

def test_login(driver):

    driver.get("https://example.com/login")

 

    driver.find_element("id", "username").send_keys("admin")

    driver.find_element("id", "password").send_keys("admin123")

    driver.find_element("id", "loginButton").click()

 

    assert "Dashboard" in driver.title

This example demonstrates how a PyTest test can control a Selenium browser and validate the result.


38. PyTest with Page Object Model

The Page Object Model (POM) separates web-page interaction logic from test logic.

Example page object:

from selenium.webdriver.common.by import By

 

class LoginPage:

 

    def __init__(self, driver):

        self.driver = driver

 

        self.username = (By.ID, "username")

        self.password = (By.ID, "password")

        self.login_button = (By.ID, "loginButton")

 

    def login(self, username, password):

        self.driver.find_element(

            *self.username

        ).send_keys(username)

 

        self.driver.find_element(

            *self.password

        ).send_keys(password)

 

        self.driver.find_element(

            *self.login_button

        ).click()


39. PyTest POM Test Example

def test_login(driver):

    driver.get("https://example.com/login")

 

    login_page = LoginPage(driver)

 

    login_page.login(

        "admin",

        "admin123"

    )

 

    assert "Dashboard" in driver.title

This approach keeps test logic cleaner and makes page interactions reusable.


40. PyTest Test Dependencies

PyTest itself has a relatively simple dependency model, but Selenium automation projects normally require additional packages.

Example requirements.txt:

pytest

selenium

Additional packages can be added based on project requirements.


41. Installing Selenium with PyTest

pip install selenium pytest

Verify PyTest:

pytest --version

Verify Selenium:

pip show selenium


42. PyTest Verbose Mode

Verbose mode provides more information about each test during execution.

pytest -v

Example conceptual output:

test_login.py::test_valid_login PASSED

test_login.py::test_invalid_login PASSED

test_search.py::test_search PASSED


43. Running Specific Test Files

A specific test file can be executed directly.

pytest tests/test_login.py

Multiple files can also be supplied:

pytest tests/test_login.py tests/test_search.py


44. Running a Specific Test Function

pytest tests/test_login.py::test_valid_login

This is useful when debugging a specific test instead of executing the complete test suite.


45. Running Tests by Keyword

The -k option can be used to select tests based on their names.

pytest -k login

This can execute tests whose names match the keyword.


46. Stopping After the First Failure

The -x option stops execution after the first failed test.

pytest -x

This can be useful while debugging a failing test suite.


47. Running a Limited Number of Failures

PyTest also supports stopping after a specified number of failures.

pytest --maxfail=2

This stops execution after two test failures.


48. PyTest Output and Test Status

PyTest commonly reports statuses such as:

StatusMeaning
PASSEDTest executed successfully.
FAILEDAssertion or test execution failed.
SKIPPEDTest was intentionally skipped.
XFAILTest was expected to fail.
XPASSExpected-failure test unexpectedly passed.
ERRORSetup, fixture, collection, or another execution error occurred.


49. PyTest Test Reports

PyTest can generate different types of reports using built-in options and plugins.

For example, a basic report can be generated in JUnit XML format:

pytest --junitxml=report.xml

HTML reports can also be generated using the appropriate PyTest reporting plugin.

pip install pytest-html

Then:

pytest --html=report.html

Reports are useful for reviewing test results and integrating automated testing into CI/CD pipelines.


50. PyTest HTML Reports

The pytest-html plugin can generate an HTML report containing test execution information.

pip install pytest-html

Run tests with:

pytest --html=report.html

The generated HTML report can contain information about passed, failed, skipped, and other test outcomes.


51. PyTest JUnit XML Reports

JUnit XML reports are commonly used by CI/CD and test management systems.

pytest --junitxml=results.xml

These reports can be consumed by various continuous integration systems and reporting tools.


52. PyTest Logging

Logging can help identify what happened during test execution.

import logging

 

def test_login():

    logging.info("Starting login test")

 

    result = True

 

    assert result is True

For larger frameworks, logging configuration can be centralized so that test execution information is stored consistently.


53. PyTest Setup and Teardown

Setup logic prepares the environment before a test, while teardown logic cleans resources after execution.

Fixtures are the preferred mechanism for many setup and teardown requirements in PyTest.

@pytest.fixture

def setup():

    print("Setup")

 

    yield

 

    print("Teardown")


54. Autouse Fixtures

An autouse fixture executes automatically without needing to explicitly request the fixture in every test.

@pytest.fixture(autouse=True)

def setup():

    print("Setup before test")

    yield

    print("Cleanup after test")

Autouse fixtures should be used carefully because they can affect many tests implicitly.


55. Fixture Dependency

One fixture can use another fixture as a dependency.

@pytest.fixture

def username():

    return "admin"

 

@pytest.fixture

def login_data(username):

    return {

        "username": username,

        "password": "admin123"

    }

 

def test_login(login_data):

    assert login_data["username"] == "admin"

This makes complex test setup easier to organize.


56. PyTest Parameterization with Multiple Values

import pytest

 

@pytest.mark.parametrize(

    "username,password",

    [

        ("admin", "admin123"),

        ("manager", "manager123"),

        ("employee", "employee123")

    ]

)

def test_login(username, password):

    assert username != ""

    assert password != ""

The same test executes for every username and password combination.


57. Parameterization with Expected Results

import pytest

 

@pytest.mark.parametrize(

    "username,password,expected",

    [

        ("admin", "admin123", True),

        ("invalid", "wrong", False),

        ("manager", "manager123", True)

    ]

)

def test_login_validation(username, password, expected):

    result = username != "invalid"

 

    assert result == expected

Expected results can be stored along with the test inputs.


58. Parameterized Selenium Search Test

import pytest

 

@pytest.mark.parametrize(

    "search_text",

    [

        "Laptop",

        "Mobile",

        "Headphones",

        "Keyboard"

    ]

)

def test_search(driver, search_text):

    driver.get("https://example.com")

 

    search_box = driver.find_element(

        "id",

        "search"

    )

 

    search_box.send_keys(search_text)

 

    assert search_text != ""


59. PyTest Fixtures and Parameterization Together

Fixtures and parameterization can be combined to build reusable Selenium tests.

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    yield driver

    driver.quit()

 

@pytest.mark.parametrize(

    "search_text",

    ["Laptop", "Mobile", "Tablet"]

)

def test_search(driver, search_text):

    driver.get("https://example.com")

 

    driver.find_element(

        "id",

        "search"

    ).send_keys(search_text)


60. PyTest with Multiple Browsers

Browser parameterization can be used to run similar Selenium tests across different browsers.

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver(request):

    browser = request.param

 

    if browser == "chrome":

        driver = webdriver.Chrome()

    elif browser == "firefox":

        driver = webdriver.Firefox()

    else:

        raise ValueError(

            f"Unsupported browser: {browser}"

        )

 

    yield driver

    driver.quit()

 

@pytest.mark.parametrize(

    "driver",

    ["chrome", "firefox"],

    indirect=True

)

def test_browser(driver):

    driver.get("https://www.google.com")

    assert driver.title != ""


61. PyTest request Fixture

The built-in request fixture provides information about the current test context and can be useful for advanced fixture designs.

@pytest.fixture

def browser(request):

    browser_name = request.param

    print("Browser:", browser_name)

This is especially useful when creating configurable browser fixtures.


62. PyTest Skip Based on Browser

Tests can be conditionally skipped depending on the browser or environment.

@pytest.mark.skip(reason="Feature unavailable in this browser")

def test_browser_specific_feature():

    assert True

Conditional logic can also be implemented through fixtures or configuration when browser-specific behavior is required.


63. PyTest Plugins

PyTest has a large ecosystem of plugins that extend its functionality.

Common examples include:

  • pytest-html: HTML test reports.
  • pytest-xdist: Parallel test execution.
  • pytest-cov: Code coverage reporting.
  • pytest-mock: Mocking support.
  • pytest-json-report: JSON-based reporting.

Plugins allow teams to customize PyTest for different automation requirements.


64. PyTest Parallel Execution

Parallel execution can reduce overall test execution time. The pytest-xdist plugin is commonly used for parallel execution.

pip install pytest-xdist

Run tests using multiple workers:

pytest -n 4

This requests four workers for parallel test execution.

When using Selenium, each parallel test should have an isolated browser session and thread-safe framework resources.


65. PyTest and Selenium Thread Safety

When Selenium tests run in parallel, WebDriver instances should generally not be shared between independent concurrent tests.

Test 1 ----> WebDriver 1 ----> Browser 1

Test 2 ----> WebDriver 2 ----> Browser 2

Test 3 ----> WebDriver 3 ----> Browser 3

Using separate browser sessions helps prevent one test from interfering with another.


66. PyTest and API Testing

Although PyTest is commonly associated with unit and Selenium testing, it can also be used for API automation.

import requests

 

def test_get_users():

    response = requests.get(

        "https://api.example.com/users"

    )

 

    assert response.status_code == 200

The same PyTest concepts such as fixtures, parameterization, markers, and assertions can be applied to API tests.


67. PyTest for Data-Driven API Testing

import pytest

import requests

 

@pytest.mark.parametrize(

    "user_id",

    [1, 2, 3]

)

def test_user_api(user_id):

    response = requests.get(

        f"https://api.example.com/users/{user_id}"

    )

 

    assert response.status_code == 200

This demonstrates how one test can validate multiple API inputs.


68. PyTest Environment Configuration

Test frameworks often need different environments such as QA, staging, and production-like environments.

def test_environment():

    environment = "QA"

    base_url = "https://qa.example.com"

 

    assert environment == "QA"

    assert base_url.startswith("https://")

In production frameworks, environment values are generally maintained through configuration rather than hard-coded throughout test files.


69. PyTest Configuration Using Environment Variables

Environment variables can be used to provide configuration values without modifying test code.

import os

 

def test_environment():

    base_url = os.getenv(

        "BASE_URL",

        "https://example.com"

    )

 

    assert base_url.startswith("https://")

This approach is useful in CI/CD environments where configuration changes between environments.


70. PyTest with Page Objects and Fixtures

A scalable Selenium framework can combine fixtures, Page Object Model, parameterization, and assertions.

@pytest.fixture

def login_page(driver):

    return LoginPage(driver)

 

def test_login(login_page):

    login_page.login(

        "admin",

        "admin123"

    )

 

    assert "Dashboard" in login_page.driver.title

This structure keeps browser management, page interactions, and test validation separated.


71. PyTest Test Organization

Large automation projects should organize tests logically.

tests/

|-- smoke/

|   |-- test_login.py

|   |-- test_home.py

|

|-- regression/

|   |-- test_search.py

|   |-- test_checkout.py

|

|-- api/

|   |-- test_users.py

|   |-- test_products.py

Markers and directory structure can be combined to improve test suite organization.


72. PyTest Smoke Testing

Smoke tests validate critical application functionality quickly after a new build or deployment.

import pytest

 

@pytest.mark.smoke

def test_login():

    assert True

 

@pytest.mark.smoke

def test_home_page():

    assert True

Smoke tests can be executed using:

pytest -m smoke


73. PyTest Regression Testing

Regression tests validate existing functionality after application changes.

import pytest

 

@pytest.mark.regression

def test_search():

    assert True

 

@pytest.mark.regression

def test_checkout():

    assert True

Regression tests can be executed using:

pytest -m regression


74. PyTest Common Mistakes

  • Incorrect test file naming.
  • Incorrect test function naming.
  • Forgetting to install PyTest.
  • Using incorrect fixture names.
  • Not closing Selenium browsers.
  • Sharing WebDriver instances unsafely between parallel tests.
  • Using excessive hard-coded test data.
  • Not using assertions properly.
  • Creating overly complicated fixtures.
  • Using too many implicit dependencies between tests.
  • Not organizing tests into logical modules.
  • Not configuring markers correctly.
  • Ignoring test failures in CI/CD.
  • Storing sensitive credentials directly in source code.


75. Common Selenium + PyTest Mistakes

MistakeBetter Approach
Creating browser in every test manuallyUse reusable fixtures.
Forgetting driver.quit()Use fixture teardown.
Sharing one driver in parallel testsUse isolated WebDriver instances.
Hard-coding URLs everywhereUse configuration.
Putting locators directly in every testUse Page Object Model.
Duplicating test dataUse parameterization or external data.


76. Best Practices for PyTest

  • Follow standard PyTest naming conventions.
  • Keep test cases small and focused.
  • Use meaningful test names.
  • Use fixtures for reusable setup and cleanup.
  • Use parameterization for data-driven tests.
  • Use markers to categorize tests.
  • Keep Selenium page interactions inside Page Objects.
  • Keep configuration separate from test logic.
  • Generate useful test reports.
  • Use logging for debugging.
  • Avoid unnecessary test dependencies.
  • Use isolated browser sessions for parallel execution.
  • Protect passwords, tokens, and other secrets.
  • Integrate automated tests into CI/CD pipelines.


77. PyTest vs unittest

FeaturePyTestunittest
SyntaxSimpleMore structured
AssertionsPython assertunittest assertion methods
FixturesPowerful fixture systemsetUp/tearDown mechanisms
ParameterizationBuilt-in through markersRequires additional approaches
PluginsLarge ecosystemSmaller ecosystem
Selenium IntegrationCommonly usedSupported


78. PyTest vs TestNG

FeaturePyTestTestNG
LanguagePythonJava
Basic AssertionassertAssert methods
Fixtures/Setuppytest.fixtureConfiguration annotations
ParameterizationparametrizeDataProvider / Parameters
MarkersYesGroups and other annotations
Web AutomationSelenium PythonSelenium Java
ReportsPlugins and formatsBuilt-in/plugin-based reporting options


79. PyTest with CI/CD

PyTest can be integrated into continuous integration and continuous delivery pipelines.

Developer Commit

      |

      v

CI/CD Pipeline

      |

      v

Install Dependencies

      |

      v

Run PyTest

      |

      v

Selenium / API Tests

      |

      v

Generate Reports

      |

      v

Build Result

This allows automated tests to execute whenever new application code is committed or deployed.


80. PyTest with Jenkins

Jenkins can execute PyTest commands as part of an automated pipeline.

pytest -v

pytest --html=report.html

pytest --junitxml=results.xml

Test reports can then be archived or processed by the CI system according to the project's reporting configuration.


81. PyTest Automation Framework Architecture

                 Test Data

                     |

                     v

              Parameterization

                     |

                     v

              PyTest Test Case

                     |

          +----------+----------+

          |                     |

          v                     v

      Fixtures              Page Objects

          |                     |

          +----------+----------+

                     |

                     v

              Selenium WebDriver

                     |

                     v

                 Web Browser

                     |

                     v

                 Application

                     |

                     v

                  Assertions

                     |

                     v

                   Reports


82. Complete Practical Selenium PyTest Example

The following example demonstrates a simple reusable Selenium PyTest framework using a fixture, Selenium WebDriver, and assertions.

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    driver.maximize_window()

 

    yield driver

 

    driver.quit()

 

def test_google_title(driver):

    driver.get("https://www.google.com")

 

    assert "Google" in driver.title

 

def test_google_url(driver):

    driver.get("https://www.google.com")

 

    assert "google" in driver.current_url.lower()


83. Practical Login Automation Example

import pytest

from selenium import webdriver

 

@pytest.fixture

def driver():

    driver = webdriver.Chrome()

    driver.maximize_window()

 

    yield driver

 

    driver.quit()

 

@pytest.mark.parametrize(

    "username,password",

    [

        ("admin", "admin123"),

        ("manager", "manager123"),

        ("employee", "employee123")

    ]

)

def test_login(driver, username, password):

    driver.get("https://example.com/login")

 

    driver.find_element(

        "id",

        "username"

    ).send_keys(username)

 

    driver.find_element(

        "id",

        "password"

    ).send_keys(password)

 

    driver.find_element(

        "id",

        "loginButton"

    ).click()

 

    assert "Dashboard" in driver.title

This example demonstrates how fixtures and parameterization can reduce duplicate Selenium test code.


84. Practical Search Testing Example

import pytest

 

@pytest.mark.parametrize(

    "keyword",

    [

        "Laptop",

        "Mobile",

        "Tablet",

        "Headphones",

        "Keyboard"

    ]

)

def test_product_search(driver, keyword):

    driver.get("https://example.com")

 

    search = driver.find_element(

        "id",

        "search"

    )

 

    search.clear()

    search.send_keys(keyword)

 

    driver.find_element(

        "id",

        "searchButton"

    ).click()

 

    assert keyword != ""


85. Practical Project Structure

selenium_pytest_project/

|-- tests/

|   |-- test_login.py

|   |-- test_search.py

|   |-- test_checkout.py

|

|-- pages/

|   |-- login_page.py

|   |-- search_page.py

|   |-- checkout_page.py

|

|-- utilities/

|   |-- config_reader.py

|   |-- driver_factory.py

|

|-- test_data/

|   |-- login_data.json

|   |-- search_data.json

|

|-- reports/

|   |-- report.html

|

|-- conftest.py

|-- pytest.ini

|-- requirements.txt


86. Recommended PyTest Framework Flow

Test Request

     |

     v

Test Data

     |

     v

PyTest Parameterization

     |

     v

Fixture

     |

     v

WebDriver

     |

     v

Page Object

     |

     v

Application

     |

     v

Assertion

     |

     v

Test Result

     |

     v

Report


87. Interview Questions on PyTest Basics

1. What is PyTest?

PyTest is a Python testing framework used to write and execute automated tests.

2. How do you install PyTest?

PyTest can be installed using pip install pytest.

3. How do you run PyTest?

The basic command is pytest.

4. What is a PyTest fixture?

A fixture provides reusable setup, test resources, data, and cleanup functionality.

5. What is conftest.py?

conftest.py is a special PyTest configuration file commonly used to define reusable fixtures and shared test configuration.

6. What is @pytest.mark.parametrize?

It allows the same test to execute with multiple sets of input data.

7. What are PyTest markers?

Markers categorize tests and allow specific groups of tests to be executed selectively.

8. How do you skip a test?

The @pytest.mark.skip marker can be used to skip a test.

9. What is xfail?

xfail marks a test as expected to fail because of a known or expected condition.

10. How do you run a specific test?

You can use a command such as pytest test_login.py::test_login.

11. How do you run tests in verbose mode?

Use pytest -v.

12. How can PyTest be used with Selenium?

Selenium WebDriver can be initialized through PyTest fixtures and used inside test functions to automate browsers.

13. Why are fixtures useful in Selenium automation?

Fixtures provide reusable browser setup and cleanup logic and help prevent duplicate WebDriver code.

14. What is parameterization?

Parameterization allows the same test logic to execute using different input values.

15. How can PyTest generate HTML reports?

The pytest-html plugin can be installed and used to generate HTML reports.

16. How can PyTest generate JUnit reports?

PyTest supports JUnit XML output using the --junitxml option.

17. What is pytest.ini?

pytest.ini is a configuration file that can define test paths, naming patterns, markers, and default options.

18. How can PyTest tests run in parallel?

The pytest-xdist plugin can be used for parallel execution.

19. What is the difference between fixture scope and test parameterization?

Fixture scope controls how often a fixture resource is created, while parameterization controls how many different data combinations a test receives.

20. What are important PyTest best practices?

Use reusable fixtures, clear test names, parameterization, Page Object Model for Selenium, meaningful assertions, organized test suites, secure configuration, and useful reporting.


88. Quick Reference Table

ConceptPurpose
pytestRuns the PyTest test suite.
assertValidates expected conditions.
@pytest.fixtureCreates reusable setup and cleanup logic.
conftest.pyStores shared fixtures and configuration.
@pytest.mark.parametrizeRuns tests with multiple data sets.
@pytest.mark.smokeCategorizes smoke tests.
@pytest.mark.regressionCategorizes regression tests.
@pytest.mark.skipSkips a test.
@pytest.mark.xfailMarks an expected failure.
pytest -vRuns tests in verbose mode.
pytest -kSelects tests using keywords.
pytest -xStops after the first failure.
--maxfailLimits the number of failures before stopping.
--htmlGenerates an HTML report with pytest-html.
--junitxmlGenerates JUnit XML output.
pytest-xdistProvides parallel test execution.


89. Learning Roadmap for PyTest

  1. Learn Python fundamentals.
  2. Understand basic software testing concepts.
  3. Install and configure PyTest.
  4. Create basic test functions.
  5. Learn assertions.
  6. Understand test discovery.
  7. Learn test classes.
  8. Learn PyTest fixtures.
  9. Understand fixture scopes.
  10. Learn conftest.py.
  11. Learn parameterization.
  12. Learn markers.
  13. Learn skip and xfail.
  14. Learn PyTest configuration.
  15. Integrate PyTest with Selenium.
  16. Learn Page Object Model.
  17. Build reusable Selenium fixtures.
  18. Learn reporting.
  19. Learn parallel execution.
  20. Integrate PyTest with CI/CD.
  21. Build a complete Selenium PyTest framework.


90. Practical Exercises

  1. Create a simple addition test using PyTest.
  2. Create a calculator test with multiple assertions.
  3. Create a login test using a Selenium fixture.
  4. Create a parameterized login test.
  5. Create a parameterized search test.
  6. Create smoke and regression markers.
  7. Create a reusable browser fixture in conftest.py.
  8. Create a Page Object Model framework.
  9. Generate an HTML test report.
  10. Generate a JUnit XML report.
  11. Run selected tests using markers.
  12. Execute tests in parallel using pytest-xdist.
  13. Integrate the test suite with a CI/CD pipeline.


91. Real-World Selenium PyTest Architecture

                 Configuration

                      |

                      v

                 conftest.py

                      |

          +-----------+-----------+

          |                       |

          v                       v

       Fixtures              Test Data

          |                       |

          +-----------+-----------+

                      |

                      v

                 PyTest Tests

                      |

                      v

              Page Object Model

                      |

                      v

              Selenium WebDriver

                      |

                      v

                    Browser

                      |

                      v

                Web Application

                      |

                      v

                  Assertions

                      |

                      v

                   Reports

                      |

                      v

                    CI/CD


92. Summary

PyTest is a powerful and flexible Python testing framework used for creating automated tests. Its simple syntax makes it easy to write basic tests, while features such as fixtures, parameterization, markers, configuration, plugins, and reporting support large automation frameworks.

For Selenium automation, PyTest can manage browser setup and cleanup through fixtures, execute tests with multiple data sets using parameterization, organize tests using markers, and separate application interaction logic through the Page Object Model.

PyTest can also be integrated with HTML and JUnit reporting, parallel execution, API testing, CI/CD systems, and other automation tools.

The combination of PyTest + Selenium + Fixtures + Parameterization + Page Object Model + Reporting provides a strong foundation for building maintainable Python-based web automation frameworks.


93. Course Resources

Learn more about Selenium automation and related testing concepts:

Final Takeaway: PyTest provides a simple yet powerful foundation for Python automation testing. When combined with Selenium WebDriver, fixtures, parameterization, Page Object Model, markers, reporting, and CI/CD, it can be used to build structured, reusable, scalable, and maintainable web automation frameworks.

whatsapp